package world;

import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;

/*
 * 1. algorithm to draw line based on the simplified algorithm on wikipidia page for Bresenahms line algorthim 
 * http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Algorithm
 * 
 */
public class ChunkConfiguration {

	public static Chunk dirtChunk()
	{
		Chunk setup= new Chunk();
		
		setup.setUpChunk();
		
		return setup;
		
	}
	public static Chunk dirtChunk(int x, int y, int z)
	{
		Chunk setup= new Chunk(x,y,z);
		
		setup.setUpChunk();
		setup.setXyz(new int[] {x,y,z});
		return setup;
		
	}
	public static Chunk stoneChunk()
	{
		
		Chunk setup= new Chunk();
		setup.setUpChunk();
		setup.setAllBlockTypes(BlockElement.Element_Stone);
		
		return setup;
	}
	public static Chunk stoneChunk(int x, int y, int z)
	{
		
		Chunk setup= new Chunk(x,y,z);
		setup.setUpChunk();
		setup.setXyz(new int[] {x,y,z});
		setup.setAllBlockTypes(BlockElement.Element_Stone);
		
		return setup;
	}
	
	public static Chunk grassAndDirtChunk()
	{
		
		Chunk setup= new Chunk();
		setup.setUpChunk();
		setup.setAllBlockTypes(BlockElement.Element_Dirt);
		
		setup.setBlockTypeHorizontally(BlockElement.Element_Grass, 14);
		//first set all to dirt
		
		//second change the two two layers of blocks to grass
		
		
		return setup;
	}
	public static Chunk grassAndDirtChunk(int x, int y, int z)
	{
		
		Chunk setup= new Chunk(x,y,z);
		//setup.
		setup.setUpChunk();
		//setup.setLoaded(true);
		setup.setSetup(true);
		
		setup.setXyz(new int[] {x,y,z});
		setup.setAllBlockTypes(BlockElement.Element_Dirt);
		
		setup.setBlockTypeHorizontally(BlockElement.Element_Grass, 0);
		//first set all to dirt
		
		//second change the two two layers of blocks to grass
		
		
		return setup;
	}
	public static Chunk airChunk()
	{
		Chunk setup= new Chunk();
		
		setup.setAllBlockTypes(BlockElement.Element_Air);
		
		return setup;
	}
	
	public static Chunk waterChunk()
	{
		
		Chunk setup= new Chunk();
		setup.setAllBlockTypes(BlockElement.Element_Water);
		return setup;
	}
	public static Chunk applyExistanceToWholeChunk(Chunk chunk)
	{
		for(int x=0;x<Chunk.BLOCKS_PER_CUBIC_CHUNK;x++)
		{
		
			for(int y=0;y<Chunk.BLOCKS_PER_CUBIC_CHUNK;y++)
			{
				for(int z=0;z<Chunk.BLOCKS_PER_CUBIC_CHUNK;z++)
				{
			
					chunk.blocks[x][y][z].SetExistance(true);
				
				}
			
			}
		}
		
		return chunk;
	}
	
	public static Chunk applyWorleyNoiseCuts(int x,int y,int z,Chunk chunk)
	{
		
		//generate five points with wirley noise in this chunk
		
		Vector3f[] points = new Vector3f[10];
		Vector4f[] output = new Vector4f[10];
		
		for( int i=0;i<points.length;i++)
		{
			float xMod=(float)(Chunk.BLOCKS_PER_CUBIC_CHUNK*Math.random())+x;
			float yMod=(float)(Chunk.BLOCKS_PER_CUBIC_CHUNK*Math.random())+y;
			float zMod=(float)(Chunk.BLOCKS_PER_CUBIC_CHUNK*Math.random())+z;
			
			float xSet=  xMod;
			float ySet=  yMod;
			float zSet=  zMod;
			
			points[i]= new Vector3f();
			points[i].set(xSet, ySet, zSet);
			String seed =""+new Float(xSet).hashCode()+""+new Float(ySet).hashCode()+""+new Float(zSet).hashCode();
		
			
			output[i]=CellNoise.CellNoiseFunc(points[i], seed.hashCode());
			
			int height= (int)(Chunk.BLOCKS_PER_CUBIC_CHUNK*output[i].y);
			
			
			int x0=(int)xMod;
			int x1=(int)(output[i].x);
			int z0=(int)zMod;
			int z1=(int)(output[i].z);;
			
			int sx;
			int sz;
			int err;
			
			//Draw a line between point in chunk and output i useing bresenhams line algorthim found at (1) 
			int dx= Math.abs(x1-x0);
			int dz= Math.abs(z1-z0);
			
			if(x0< x1) 
			{
			sx=1;	
			}
			else
			{
			sx=-1;	
			}
			
			if(z0< z1) 
			{
			sz=1;	
			}
			else
			{
			sz=-1;	
			}
			
			err = dx-dz;
			
			while(x0!=x1 && z0!=z1 &&x0<16 &&z0<16)
			{
				for(int j=1;j<Chunk.BLOCKS_PER_CUBIC_CHUNK;j++ )
				{
				if(j<=height)
				{
					chunk.blocks[x0][j][z0].SetExistance(false);	
				}
				else
				{
				//	chunk.blocks[x0][j][z0].SetExistance(false);	
				}
				}
				
			int e2=2*err;	
			if(e2>- dz)
			{
				err=err-dz;
				x0=x0+sx;
			}
			
			if(e2< dx)
			{
				err=err+dx;
				z0=z0+sz;
			}
			
			}
			
			
		}
		
	
		
		//draw a line with voxels between point i and output i
		
		
			//cellNoise.z*=15;
			//double height= cellNoise.y;
			//System.err.println("height "+height);
			//height = Math.abs(height);
			
			//height *= Chunk.BLOCKS_PER_CUBIC_CHUNK-1;
			
			//System.err.println("Height: "+height);
			//System.err.println("Height as an int" +(int)height);
			//System.err.println("height "+height);
			
			
			//System.err.println("height: "+height);
			
				
				
				
				//Vector4f cellNoise=CellNoise.CellNoiseFunc(input, seed.hashCode());
				//cellNoise.x*=15;
				//cellNoise.y*=15;
				
				
					//System.err.println("blocks exist: "+yCounter);
					//if(cellNoise.x*16==xCounter&& cellNoise.z*16==zCounter)
					//{
				//if(cellNoise.x*15==xCounter&& cellNoise.z*15==zCounter){
				
				//}//end if
				
			
			
			
			
			
		
		return chunk;
	}
	public static Chunk applyWorleyNoise(int x,int y,int z,Chunk chunk, double zMod,double yMod,double xMod)
	{
		int heightMod=5;
		for(int xCounter=0;xCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;xCounter++)
		{
		
		for(int zCounter=0;zCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;zCounter++)
		{
			int currentHeight=0;
			for(int yCounter=0; yCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;yCounter++)
			{
				if(chunk.blocks[xCounter][yCounter][zCounter].exists())
				{
					currentHeight++;
				}
			}	
				
				Float seedX=(float)(x+(xCounter));
				Float seedY=(float) (y);
				Float seedZ=(float) (z+(zCounter));	
			Vector3f input = new Vector3f();
			input.set(seedX,seedY,seedZ);
			
			
			
			int seed = seedY.hashCode();
			Vector4f output=CellNoise.CellNoiseFunc(input, seed);  
			
			//System.err.println("output to String: "+output.toString());
			
			
			double height= output.y;
			
		    height*=heightMod;
			
			//System.err.println("Height before: "+height);
			
			//System.err.println("Height after: "+height);
			//height = Math.abs(height);
			
			//height *=10;
			
			
			//System.err.println("Height as an int" +(int)height);
			
			
			
			//System.err.println("height: "+height);
			
				/*for(int yCounter=0; yCounter<height;yCounter++)
				{
					//System.err.println("blocks exist: "+yCounter);
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(true);
					//System.err.println("existance"+)
				}*/
				//if(currentHeight>height)
				//{
				
				for(int yCounter=1;yCounter<height;yCounter++)
				{
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(false);
					
				}
				
				//}
				//else
				//{
					
				//}
			
			
			
			
		
		}
		}
		return chunk;
	}
	public void bresignham3d(Chunk chunk)
	{
		
	}
	
	
	public static Chunk applySimplexNoise(int x,int y,int z,Chunk chunk, double zMod,double xMod)
	{
		for(int xCounter=0;xCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;xCounter++)
		{
		
		for(int zCounter=0;zCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;zCounter++)
		{
			
			
			
			double height=Noise.simplexNoise2D((x+xCounter*xMod)*xMod,(z+zCounter*xMod)*zMod);
			
			height = Math.abs(height);
			
			height *= Chunk.BLOCKS_PER_CUBIC_CHUNK-1;
			
			//System.err.println("Height: "+height);
			//System.err.println("Height as an int" +(int)height);
			
			
			
			//System.err.println("height: "+height);
			
				for(int yCounter=0; yCounter<height;yCounter++)
				{
					//System.err.println("blocks exist: "+yCounter);
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(true);
					//System.err.println("existance"+)
				}
				
				/*for(int yCounter=(int)height;yCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;yCounter++)
				{
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(false);
					
				}*/
			
			
			
			
			
		}
		
		}
		return chunk;
	}
	public static Chunk applyPerlinNoise(int x,int y,int z,Chunk chunk, double zMod,double xMod)
	{
		for(int xCounter=0;xCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;xCounter++)
		{
		
		for(int zCounter=0;zCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;zCounter++)
		{
			
			
			
			double height=PerlinNoise.noise((x+xCounter*xMod)*xMod,y,(z+zCounter*xMod)*zMod);
			
			height = Math.abs(height);
			
			height *= Chunk.BLOCKS_PER_CUBIC_CHUNK-1;
			
			//System.err.println("Height: "+height);
			//System.err.println("Height as an int" +(int)height);
			
			
			
			//System.err.println("height: "+height);
			
				for(int yCounter=0; yCounter<height;yCounter++)
				{
					//System.err.println("blocks exist: "+yCounter);
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(true);
					//System.err.println("existance"+)
				}
				
				/*for(int yCounter=(int)height;yCounter<Chunk.BLOCKS_PER_CUBIC_CHUNK;yCounter++)
				{
					chunk.blocks[xCounter][yCounter][zCounter].SetExistance(false);
					
				}*/
			
			
			
			
			
		}
		
		}
		return chunk;
	}
}
